-
Notifications
You must be signed in to change notification settings - Fork 162
Add Clash.Class.NumConvert
#2915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
I'd vote against naming it (I really want to make the silly pun |
d8f851c
to
25c7757
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall.
I'm going to accept this, because I cannot see anything really controversial in the sense that it would be hard to fix it later on.
Regarding the Convert
vs Convertible
question: I don't like either name, as they both suggest much freedom in terms of which types could be converted with the classes. Your documentation clearly restricts the setting to number types, which is in contrast to Convertible
for example, which is also open for conversion between custom non-number types. So maybe we should keep the users of that package happy by not producing any name clash at this point.
A name like changeNumType
would make it more clear to me what the purpose of this function is. Convert
, Convertible
, and convert
are just super generic names!
I still find it strange to consider BitVector
a number type. If we are going to have a discussion about this at some point, then I'd suggest to keep it out here for the time being. Adding it later is easy and the user still can define the instance locally, if necessary.
I don't like the fact that we need to have two classes in the end, but I get the point that the need for individual selection of constraints per instance introduces that requirement.
Thanks for the comments @kleinreact, I'll get to them, though I'm fairly time constrained at the moment :(. I think your comment about the name |
Somehow I feel Also, we could rewrite the laws such that the class can also be used for non-numbers. I think that would work? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also feel Convert
is too generic a name and squats too much, except if it is only to be used qualified. I'm personally leaning towards renaming it NumConvert
, numConvert
, MaybeNumConvert
and maybeNumConvert
as the names used, and exporting them from Prelude
. Note that you currently to not export them from Prelude
, I'd like that to be added.
Something I noticed is that for Convert
, you seem to put a bang pattern only on the instances that need one to preserve the XException
, yet on MaybeConvert
you just bang almost everything. Was this intended? I'm not against it, I'm just wondering.
@DigitalBrains1 For some reason GitHub doesn't let me reply to your comment on the word total, so I'll reply here: totally fair criticism! I think lossless is the word I want to use. (After rephrasing the sentence a bit.) |
Yeah, that's a confusing formatting issue. As part of a review, you can reply to an earlier review comment. It then shows it in the original place where you can reply, and also as part of the new review. If you click on the date in the header of the latter (3 weeks ago it currently says), you can go to the former and comment... why they did this, I don't know. I think lossless is fair, although you could argue that [edit]
Wait, was that a pun? Did I miss a pun on my first read? X-D |
Me? Puns? I wouldn't dare! |
0ba7f07
to
73d2424
Compare
13064f3
to
b805b7b
Compare
b805b7b
to
42406b1
Compare
I've done a couple of things (now hidden in resolved conversations):
I think I got to all the comments. |
I mostly followed the error messages brought up by the tests. TBF, it is a bit too much for me to do precisely so I might have been over eager.. |
9a88bca
to
d74051a
Compare
Utilities for safely converting between various Clash number types
d74051a
to
530541f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work on the improvements! It did introduce a few more issues, but I think after that, that should be it. As discussed, I will add the improvements as a commit to save you the trouble. But the commit follows tomorrow, I'm already past out of time right now.
between different number types (e.g., 'Clash.Sized.Unsigned.Unsigned' to | ||
'Clash.Sized.Signed.Signed') and that it is not always clear how to do so | ||
properly. Two classes are exported: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
between different number types (e.g., 'Clash.Sized.Unsigned.Unsigned' to | |
'Clash.Sized.Signed.Signed') and that it is not always clear how to do so | |
properly. Two classes are exported: | |
between different number types (e.g., @Unsigned@ to @Signed@) and that it is not | |
always clear how to do so properly. Two classes are exported: |
With GHC 8.10, you cannot link to qualified type names :-(. Only terms. If you want to link to a type, you need to import it and use it unqualified in the Haddock.
1. It offers no partial functions. | ||
2. All its conversions are translatable to synthesizable HDL. | ||
3. It is focused on (Clash's) number types |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stupid little stylistic detail: either all these sentence fragments need to omit the period, or they all should have a period. I do believe I omit the period when I add documentation.
> x == fromMaybe x (maybeNumConvert @a @b x >>= maybeNumConvert @b @a) | ||
|
||
for all values @x@ of type @a@. It should also preserve the numerical value | ||
interpretation of the bits. For types that have an "Integral" instance, this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interpretation of the bits. For types that have an "Integral" instance, this | |
interpretation of the bits. For types that have an @Integral@ instance, this |
Double quotes link to modules, not declarations. I don't think the type is in scope, so let's just use typewriter font.
> isJust (maybeNumConvert @a @b x) `implies` isJust (maybeNumConvert @a @b x >>= maybeNumConvert @b @a) | ||
|
||
A conversion should succeed if and only if the value is representable in the | ||
target type. For types that have a "Bounded" and "Integral" instance, this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
target type. For types that have a "Bounded" and "Integral" instance, this | |
target type. For types that have a @Bounded@ and @Integral@ instance, this |
> Just x == maybeNumConvert (numConvert @a @b x) | ||
|
||
for all values @x@ of type @a@. It should also preserve the numerical value | ||
interpretation of the bits. For types that have an "Integral" instance, this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interpretation of the bits. For types that have an "Integral" instance, this | |
interpretation of the bits. For types that have an @Integral@ instance, this |
|
||
Instances should make sure their constraints are as \"tight\" as possible. I.e., | ||
if an instance's constraints cannot be satisfied, then for the same types | ||
'Clash.Class.NumConvert.maybeConvert' should return 'Nothing' for one or more |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'Clash.Class.NumConvert.maybeConvert' should return 'Nothing' for one or more | |
'Clash.Class.NumConvert.maybeNumConvert' should return 'Nothing' for one or more |
Additionally, any implementation should be translatable to synthesizable HDL. | ||
-} | ||
class MaybeNumConvert a b where | ||
{- | NumConvert a supplied value of type @a@ to a value of type @b@. If the value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{- | NumConvert a supplied value of type @a@ to a value of type @b@. If the value | |
{- | Convert a supplied value of type @a@ to a value of type @b@. If the value |
As discussed
Additionally, any implementation should be translatable to synthesizable HDL. | ||
-} | ||
class NumConvert a b where | ||
{- | NumConvert a supplied value of type @a@ to a value of type @b@. The conversion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{- | NumConvert a supplied value of type @a@ to a value of type @b@. The conversion | |
{- | Convert a supplied value of type @a@ to a value of type @b@. The conversion |
As discussed
-- | Checks whether an 'XException' in, means an 'XException' out | ||
convertXException :: forall a b. (MaybeNumConvert a b) => Proxy a -> Proxy b -> Bool | ||
convertXException _ _ = isLeft $ isX $ maybeNumConvert @a @b (errorX "" :: a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-- | Checks whether an 'XException' in, means an 'XException' out | |
convertXException :: forall a b. (MaybeNumConvert a b) => Proxy a -> Proxy b -> Bool | |
convertXException _ _ = isLeft $ isX $ maybeNumConvert @a @b (errorX "" :: a) | |
-- | Checks whether an 'XException' in, means an 'XException' out | |
convertXException :: forall a b. (MaybeNumConvert a b) => Proxy a -> Proxy b -> Bool | |
convertXException _ _ = case isX $ maybeNumConvert @a @b (errorX "BOO" :: a) of | |
Left s -> "BOO" `L.isInfixOf` s | |
Right _ -> False |
Needs some adjustments to imports too. But the test passes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errorX "BOO"
👻
(since Haskell supports Unicode, you could use that as the error message)
.
.
.
(please don't use errorX "👻"
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, I've added a commit implementing my change requests. When you squash the merge, please remove the Co-authored by Peter, a bit of review is not co-authorship.
Thank you :) |
Utilities for safely converting between various Clash number types.
To discuss / investigate (but maybe not for this PR?)
1 <= n
constraints to every result where the result isIndex n
Index 0
has no inhabitants, so we cannot create it. On the other hand, we can of course just callerrorX "foo"
. I'm not sure whether I would say this violates the "guaranteed to succeed" rule.1 <= n
constraints to every argument where the argument isIndex n
convert
andmaybeConvert
will always returnXException
if given anXException
.BitVector 0
toIndex
/Unsigned
/Signed
? The HDL will happily do it, why wouldn't Clash simulation? Similarly, anyBitVector n
could be repacked to be partially undefined if converted to anotherBitVector m
wherem > n
.I'd push for kicking these questions to after this PR, because:
XException
behavior (but not introduce it).clash-prelude
.Still TODO:
Decide whether to call itClash.Class.Convert
orClash.Class.Convertible
. The latter has some buy-in (?) from the community, given thatcovertible
already exists. On the other hand, this might make users think it isconvertible
, but it isn't.NumConvert
!